﻿using CK.Sprite.Cache;
using CK.Sprite.Framework;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace CK.Sprite.Form.Core
{
    public class CommonService : DomainService
    {
        public ICacheSendNotice CacheSendNotice => LazyGetRequiredService(ref _cacheSendNotice);
        private ICacheSendNotice _cacheSendNotice;

        private string applicationCode;

        #region WrapInfo Operate

        public async Task AddWrapInfo(WrapInfoCreateDto wrapInfoCreateDto)
        {
            var wrapInfo = Mapper.Map<WrapInfoCreateDto, WrapInfo>(wrapInfoCreateDto);
            wrapInfo.Id = Guid.NewGuid();

            await _serviceProvider.DoDapperServiceAsync(DefaultDbConfig, async (unitOfWork) =>
            {
                var wrapInfoRepository = new GuidRepositoryBase<WrapInfo>(unitOfWork);
                var wrapInfoHandler = _serviceProvider.GetService<WrapInfoHandler>();
                wrapInfoHandler.SetNext(null, unitOfWork);
                await wrapInfoHandler.AddWrapInfo(wrapInfo, wrapInfoRepository);

                await ChangeWrapInfo(wrapInfo, unitOfWork);
            });
        }

        public async Task UpdateWrapInfo(WrapInfoUpdateDto wrapInfoUpdateDto)
        {
            await _serviceProvider.DoDapperServiceAsync(DefaultDbConfig, async (unitOfWork) =>
            {
                var wrapInfoRepository = new GuidRepositoryBase<WrapInfo>(unitOfWork);
                var wrapInfo = await wrapInfoRepository.GetAsync(wrapInfoUpdateDto.Id);
                if (wrapInfo == null)
                {
                    throw new SpriteException("未找到WrapInfo数据信息");
                }
                Mapper.Map(wrapInfoUpdateDto, wrapInfo);
                var wrapInfoHandler = _serviceProvider.GetService<WrapInfoHandler>();
                wrapInfoHandler.SetNext(null, unitOfWork);
                await wrapInfoHandler.UpdateWrapInfo(wrapInfo, wrapInfoRepository);

                await ChangeWrapInfo(wrapInfo, unitOfWork);
            });
        }

        public async Task DeleteWrapInfo(Guid id)
        {
            await _serviceProvider.DoDapperServiceAsync(DefaultDbConfig, async (unitOfWork) =>
            {
                var wrapInfoRepository = new GuidRepositoryBase<WrapInfo>(unitOfWork);
                var deleteData = await wrapInfoRepository.GetAsync(id);
                if (deleteData == null)
                {
                    throw new SpriteException("未找到WrapInfo数据信息");
                }
                var wrapInfoHandler = _serviceProvider.GetService<WrapInfoHandler>();
                wrapInfoHandler.SetNext(null, unitOfWork);
                await wrapInfoHandler.DeleteWrapInfo(deleteData, wrapInfoRepository);

                await ChangeWrapInfo(deleteData, unitOfWork);
            });
        }

        public async Task<List<WrapInfo>> GetListWrapInfoAsync(Guid businessId)
        {
            return await _serviceProvider.DoDapperServiceAsync(DefaultDbConfig, async (unitOfWork) =>
            {
                var spriteCommonRepository = ConnectionFactory.GetConnectionProvider(DefaultDbConfig.ConnectionType).GetRepository<ISpriteCommonRepository>(unitOfWork);
                List<QueryWhereModel> queryWhereModels = new List<QueryWhereModel>()
                {
                    new QueryWhereModel()
                    {
                        Field = "BusinessId",
                        ConditionType = EConditionType.等于,
                        Value = businessId
                    }
                };
                var result = await spriteCommonRepository.GetCommonList<WrapInfo>("WrapInfos", queryWhereModels);
                return result;
            });
        }

        private async Task ChangeWrapInfo(WrapInfo wrapInfo, IUnitOfWork unitOfWork)
        {
            switch (wrapInfo.BusinessCategory)
            {
                case "View":
                    var spriteViewRepository = ConnectionFactory.GetConnectionProvider(DefaultDbConfig.ConnectionType).GetRepository<ISpriteViewRepository>(unitOfWork);
                    var spriteViewHandler = _serviceProvider.GetService<SpriteViewHandler>();
                    spriteViewHandler.SetNext(null, unitOfWork);
                    await spriteViewHandler.ChangeWrapInfo(wrapInfo.BusinessId, spriteViewRepository);
                    applicationCode = await spriteViewRepository.GetApplicationCodeAsync(CommonConsts.SpriteViewTableName, wrapInfo.BusinessId);
                    CacheSendNotice.SendClearCache($"{CommonConsts.SpriteFormCachePreKey}-{applicationCode}_{CommonConsts.SpriteViewCacheKey}");
                    break;
                case "Form":
                    var spriteFormRepository = ConnectionFactory.GetConnectionProvider(DefaultDbConfig.ConnectionType).GetRepository<ISpriteFormRepository>(unitOfWork);
                    var spriteFormHandler = _serviceProvider.GetService<SpriteFormHandler>();
                    spriteFormHandler.SetNext(null, unitOfWork);
                    await spriteFormHandler.ChangeWrapInfo(wrapInfo.BusinessId, spriteFormRepository);
                    applicationCode = await spriteFormRepository.GetApplicationCodeAsync(CommonConsts.SpriteFormTableName, wrapInfo.BusinessId);
                    CacheSendNotice.SendClearCache($"{CommonConsts.SpriteFormCachePreKey}-{applicationCode}_{CommonConsts.SpriteFormCacheKey}");
                    break;
            }
        }

        #endregion

        #region Control Operate

        public async Task AddControl(ControlCreateDto controlCreateDto)
        {
            var control = Mapper.Map<ControlCreateDto, Control>(controlCreateDto);
            control.Id = Guid.NewGuid();

            await _serviceProvider.DoDapperServiceAsync(DefaultDbConfig, async (unitOfWork) =>
            {
                var controlRepository = new GuidRepositoryBase<Control>(unitOfWork);
                var controlHandler = _serviceProvider.GetService<ControlHandler>();
                controlHandler.SetNext(null, unitOfWork);
                await controlHandler.AddControl(control, controlRepository);

                await ChangeControl(control, unitOfWork);
            });
        }

        public async Task UpdateControl(ControlUpdateDto controlUpdateDto)
        {
            await _serviceProvider.DoDapperServiceAsync(DefaultDbConfig, async (unitOfWork) =>
            {
                var controlRepository = new GuidRepositoryBase<Control>(unitOfWork);
                var control = await controlRepository.GetAsync(controlUpdateDto.Id);
                if (control == null)
                {
                    throw new SpriteException("未找到Control数据信息");
                }
                Mapper.Map(controlUpdateDto, control);
                var controlHandler = _serviceProvider.GetService<ControlHandler>();
                controlHandler.SetNext(null, unitOfWork);
                await controlHandler.UpdateControl(control, controlRepository);

                await ChangeControl(control, unitOfWork);
            });
        }

        public async Task DeleteControl(Guid id)
        {
            await _serviceProvider.DoDapperServiceAsync(DefaultDbConfig, async (unitOfWork) =>
            {
                var controlRepository = new GuidRepositoryBase<Control>(unitOfWork);
                var deleteData = await controlRepository.GetAsync(id);
                if (deleteData == null)
                {
                    throw new SpriteException("未找到Control数据信息");
                }
                var controlHandler = _serviceProvider.GetService<ControlHandler>();
                controlHandler.SetNext(null, unitOfWork);
                await controlHandler.DeleteControl(deleteData, controlRepository);

                await ChangeControl(deleteData, unitOfWork);
            });
        }

        public async Task<List<Control>> GetListControlAsync(Guid businessId)
        {
            return await _serviceProvider.DoDapperServiceAsync(DefaultDbConfig, async (unitOfWork) =>
            {
                var spriteCommonRepository = ConnectionFactory.GetConnectionProvider(DefaultDbConfig.ConnectionType).GetRepository<ISpriteCommonRepository>(unitOfWork);
                List<QueryWhereModel> queryWhereModels = new List<QueryWhereModel>()
                {
                    new QueryWhereModel()
                    {
                        Field = "BusinessId",
                        ConditionType = EConditionType.等于,
                        Value = businessId
                    }
                };
                var result = await spriteCommonRepository.GetCommonList<Control>("Controls", queryWhereModels);
                return result;
            });
        }

        private async Task ChangeControl(Control control, IUnitOfWork unitOfWork)
        {
            switch (control.BusinessCategory)
            {
                case "View":
                    var spriteViewRepository = ConnectionFactory.GetConnectionProvider(DefaultDbConfig.ConnectionType).GetRepository<ISpriteViewRepository>(unitOfWork);
                    var spriteViewHandler = _serviceProvider.GetService<SpriteViewHandler>();
                    spriteViewHandler.SetNext(null, unitOfWork);
                    await spriteViewHandler.ChangeControl(control.BusinessId, spriteViewRepository);
                    applicationCode = await spriteViewRepository.GetApplicationCodeAsync(CommonConsts.SpriteViewTableName, control.BusinessId);
                    CacheSendNotice.SendClearCache($"{CommonConsts.SpriteFormCachePreKey}-{applicationCode}_{CommonConsts.SpriteViewCacheKey}");
                    break;
                case "Form":
                    var spriteFormRepository = ConnectionFactory.GetConnectionProvider(DefaultDbConfig.ConnectionType).GetRepository<ISpriteFormRepository>(unitOfWork);
                    var spriteFormHandler = _serviceProvider.GetService<SpriteFormHandler>();
                    spriteFormHandler.SetNext(null, unitOfWork);
                    await spriteFormHandler.ChangeControl(control.BusinessId, spriteFormRepository);
                    applicationCode = await spriteFormRepository.GetApplicationCodeAsync(CommonConsts.SpriteFormTableName, control.BusinessId);
                    CacheSendNotice.SendClearCache($"{CommonConsts.SpriteFormCachePreKey}-{applicationCode}_{CommonConsts.SpriteFormCacheKey}");
                    break;
            }
        }

        #endregion

        #region SpriteRule Operate

        public async Task AddSpriteRule(SpriteRuleCreateDto spriteRuleCreateDto)
        {
            var spriteRule = Mapper.Map<SpriteRuleCreateDto, SpriteRule>(spriteRuleCreateDto);
            spriteRule.Id = Guid.NewGuid();

            await _serviceProvider.DoDapperServiceAsync(DefaultDbConfig, async (unitOfWork) =>
            {
                var spriteRuleRepository = new GuidRepositoryBase<SpriteRule>(unitOfWork);
                var spriteRuleHandler = _serviceProvider.GetService<SpriteRuleHandler>();
                spriteRuleHandler.SetNext(null, unitOfWork);
                await spriteRuleHandler.AddSpriteRule(spriteRule, spriteRuleRepository);

                await ChangeSpriteRule(spriteRule, unitOfWork);
            });
        }

        public async Task UpdateSpriteRule(SpriteRuleUpdateDto spriteRuleUpdateDto)
        {
            await _serviceProvider.DoDapperServiceAsync(DefaultDbConfig, async (unitOfWork) =>
            {
                var spriteRuleRepository = new GuidRepositoryBase<SpriteRule>(unitOfWork);
                var spriteRule = await spriteRuleRepository.GetAsync(spriteRuleUpdateDto.Id);
                if (spriteRule == null)
                {
                    throw new SpriteException("未找到SpriteRule数据信息");
                }
                Mapper.Map(spriteRuleUpdateDto, spriteRule);
                var spriteRuleHandler = _serviceProvider.GetService<SpriteRuleHandler>();
                spriteRuleHandler.SetNext(null, unitOfWork);
                await spriteRuleHandler.UpdateSpriteRule(spriteRule, spriteRuleRepository);

                await ChangeSpriteRule(spriteRule, unitOfWork);
            });
        }

        public async Task DeleteSpriteRule(Guid id)
        {
            await _serviceProvider.DoDapperServiceAsync(DefaultDbConfig, async (unitOfWork) =>
            {
                var spriteRuleRepository = new GuidRepositoryBase<SpriteRule>(unitOfWork);
                var deleteData = await spriteRuleRepository.GetAsync(id);
                if (deleteData == null)
                {
                    throw new SpriteException("未找到SpriteRule数据信息");
                }
                var spriteRuleHandler = _serviceProvider.GetService<SpriteRuleHandler>();
                spriteRuleHandler.SetNext(null, unitOfWork);
                await spriteRuleHandler.DeleteSpriteRule(deleteData, spriteRuleRepository);

                await ChangeSpriteRule(deleteData, unitOfWork);
            });
        }

        public async Task<List<SpriteRule>> GetListSpriteRuleAsync(Guid businessId)
        {
            return await _serviceProvider.DoDapperServiceAsync(DefaultDbConfig, async (unitOfWork) =>
            {
                var spriteCommonRepository = ConnectionFactory.GetConnectionProvider(DefaultDbConfig.ConnectionType).GetRepository<ISpriteCommonRepository>(unitOfWork);
                List<QueryWhereModel> queryWhereModels = new List<QueryWhereModel>()
                {
                    new QueryWhereModel()
                    {
                        Field = "BusinessId",
                        ConditionType = EConditionType.等于,
                        Value = businessId
                    }
                };
                var result = await spriteCommonRepository.GetCommonList<SpriteRule>("SpriteRules", queryWhereModels);
                return result;
            });
        }

        private async Task ChangeSpriteRule(SpriteRule spriteRule, IUnitOfWork unitOfWork)
        {
            switch (spriteRule.BusinessCategory)
            {
                case "View":
                    var spriteViewRepository = ConnectionFactory.GetConnectionProvider(DefaultDbConfig.ConnectionType).GetRepository<ISpriteViewRepository>(unitOfWork);
                    var spriteViewHandler = _serviceProvider.GetService<SpriteViewHandler>();
                    spriteViewHandler.SetNext(null, unitOfWork);
                    await spriteViewHandler.ChangeRuleOrAction(spriteRule.BusinessId, spriteViewRepository);
                    applicationCode = await spriteViewRepository.GetApplicationCodeAsync(CommonConsts.SpriteViewTableName, spriteRule.BusinessId);
                    CacheSendNotice.SendClearCache($"{CommonConsts.SpriteFormCachePreKey}-{applicationCode}_{CommonConsts.SpriteViewCacheKey}");
                    break;
                case "Form":
                    var spriteFormRepository = ConnectionFactory.GetConnectionProvider(DefaultDbConfig.ConnectionType).GetRepository<ISpriteFormRepository>(unitOfWork);
                    var spriteFormHandler = _serviceProvider.GetService<SpriteFormHandler>();
                    spriteFormHandler.SetNext(null, unitOfWork);
                    await spriteFormHandler.ChangeRuleOrAction(spriteRule.BusinessId, spriteFormRepository);
                    applicationCode = await spriteFormRepository.GetApplicationCodeAsync(CommonConsts.SpriteFormTableName, spriteRule.BusinessId);
                    CacheSendNotice.SendClearCache($"{CommonConsts.SpriteFormCachePreKey}-{applicationCode}_{CommonConsts.SpriteFormCacheKey}");
                    break;
            }
        }

        #endregion

        #region RuleAction Operate

        public async Task AddRuleAction(RuleActionCreateDto ruleActionCreateDto)
        {
            var ruleAction = Mapper.Map<RuleActionCreateDto, RuleAction>(ruleActionCreateDto);
            ruleAction.Id = Guid.NewGuid();

            await _serviceProvider.DoDapperServiceAsync(DefaultDbConfig, async (unitOfWork) =>
            {
                var ruleActionRepository = new GuidRepositoryBase<RuleAction>(unitOfWork);
                var ruleActionHandler = _serviceProvider.GetService<RuleActionHandler>();
                ruleActionHandler.SetNext(null, unitOfWork);
                await ruleActionHandler.AddRuleAction(ruleAction, ruleActionRepository);

                await ChangeRuleAction(ruleAction, unitOfWork);
            });
        }

        public async Task UpdateRuleAction(RuleActionUpdateDto ruleActionUpdateDto)
        {
            await _serviceProvider.DoDapperServiceAsync(DefaultDbConfig, async (unitOfWork) =>
            {
                var ruleActionRepository = new GuidRepositoryBase<RuleAction>(unitOfWork);
                var ruleAction = await ruleActionRepository.GetAsync(ruleActionUpdateDto.Id);
                if (ruleAction == null)
                {
                    throw new SpriteException("未找到RuleAction数据信息");
                }
                Mapper.Map(ruleActionUpdateDto, ruleAction);
                var ruleActionHandler = _serviceProvider.GetService<RuleActionHandler>();
                ruleActionHandler.SetNext(null, unitOfWork);
                await ruleActionHandler.UpdateRuleAction(ruleAction, ruleActionRepository);

                await ChangeRuleAction(ruleAction, unitOfWork);
            });
        }

        public async Task DeleteRuleAction(Guid id)
        {
            await _serviceProvider.DoDapperServiceAsync(DefaultDbConfig, async (unitOfWork) =>
            {
                var ruleActionRepository = new GuidRepositoryBase<RuleAction>(unitOfWork);
                var deleteData = await ruleActionRepository.GetAsync(id);
                if (deleteData == null)
                {
                    throw new SpriteException("未找到RuleAction数据信息");
                }
                var ruleActionHandler = _serviceProvider.GetService<RuleActionHandler>();
                ruleActionHandler.SetNext(null, unitOfWork);
                await ruleActionHandler.DeleteRuleAction(deleteData, ruleActionRepository);

                await ChangeRuleAction(deleteData, unitOfWork);
            });
        }

        public async Task<List<RuleAction>> GetListRuleActionAsync(Guid ruleId)
        {
            return await _serviceProvider.DoDapperServiceAsync(DefaultDbConfig, async (unitOfWork) =>
            {
                var spriteCommonRepository = ConnectionFactory.GetConnectionProvider(DefaultDbConfig.ConnectionType).GetRepository<ISpriteCommonRepository>(unitOfWork);
                List<QueryWhereModel> queryWhereModels = new List<QueryWhereModel>()
                {
                    new QueryWhereModel()
                    {
                        Field = "RuleId",
                        ConditionType = EConditionType.等于,
                        Value = ruleId
                    }
                };
                var result = await spriteCommonRepository.GetCommonList<RuleAction>("RuleActions", queryWhereModels);
                return result;
            });
        }

        private async Task ChangeRuleAction(RuleAction ruleAction, IUnitOfWork unitOfWork)
        {
            switch (ruleAction.BusinessCategory)
            {
                case "View":
                    var spriteViewRepository = ConnectionFactory.GetConnectionProvider(DefaultDbConfig.ConnectionType).GetRepository<ISpriteViewRepository>(unitOfWork);
                    var spriteViewHandler = _serviceProvider.GetService<SpriteViewHandler>();
                    spriteViewHandler.SetNext(null, unitOfWork);
                    await spriteViewHandler.ChangeRuleOrAction(ruleAction.BusinessId, spriteViewRepository);
                    applicationCode = await spriteViewRepository.GetApplicationCodeAsync(CommonConsts.SpriteViewTableName, ruleAction.BusinessId);
                    CacheSendNotice.SendClearCache($"{CommonConsts.SpriteFormCachePreKey}-{applicationCode}_{CommonConsts.SpriteViewCacheKey}");
                    break;
                case "Form":
                    var spriteFormRepository = ConnectionFactory.GetConnectionProvider(DefaultDbConfig.ConnectionType).GetRepository<ISpriteFormRepository>(unitOfWork);
                    var spriteFormHandler = _serviceProvider.GetService<SpriteFormHandler>();
                    spriteFormHandler.SetNext(null, unitOfWork);
                    await spriteFormHandler.ChangeRuleOrAction(ruleAction.BusinessId, spriteFormRepository);
                    applicationCode = await spriteFormRepository.GetApplicationCodeAsync(CommonConsts.SpriteFormTableName, ruleAction.BusinessId);
                    CacheSendNotice.SendClearCache($"{CommonConsts.SpriteFormCachePreKey}-{applicationCode}_{CommonConsts.SpriteFormCacheKey}");
                    break;
            }
        }

        #endregion

        public async Task<T> GetDataById<T>(string tableName, Guid id)
        {
            return await _serviceProvider.DoDapperServiceAsync(DefaultDbConfig, async (unitOfWork) =>
            {
                var spriteCommonRepository = ConnectionFactory.GetConnectionProvider(DefaultDbConfig.ConnectionType).GetRepository<ISpriteCommonRepository>(unitOfWork);
                return await spriteCommonRepository.GetDataById<T>(tableName, id);
            });
        }
    }
}
